/*
 *  MilovoCommonFuncs.cpp
 *  Milovo04alfa00
 *
 *  Created by Luca on 10/11/06.
 *  Copyright 2006 __MyCompanyName__. All rights reserved.
 *
 */

#include "MilovoCommonFuncs.h"

vector<Mil_Int> ExtractVectIDArtifactsAvailableThisAgent(Mil_Int tmpIDAgent, Artifacts *tmp_Tab_Artifacts, int CurrentDebugLevel)
{
//	Aims of this function is to extract into a temporary vector of type Mil_Int, every artifacts (ID of) knowed by current agent
//	excluded those artifacts produced by itself. This function actually is usefull only for initializate agents network.
	
	vector<Mil_Int> tmpVectIDArtifactsAvailableThisAgent;
	for(Artifacts::iterator TabArtifactsIter = tmp_Tab_Artifacts->begin(); TabArtifactsIter != tmp_Tab_Artifacts->end(); TabArtifactsIter++)
	{
		if(TabArtifactsIter->second.GetIDAgentOwner() != tmpIDAgent)
			tmpVectIDArtifactsAvailableThisAgent.push_back(TabArtifactsIter->second.GetID());
	}
	
	if((CurrentDebugLevel >= 0) && (tmpVectIDArtifactsAvailableThisAgent.size() <= 0))
	{
		cout << "Some error in ExtractVectIDArtifactsAvailableThisAgent function: there aren't ID available (raw materials are included)" << endl;
		exit(EXIT_FAILURE);
	}
	
	return(tmpVectIDArtifactsAvailableThisAgent);
}

Mil_Int CalcOutputThisRecipe(list<Mil_Int> &ListIDIntputRecipe, list<Mil_Int> &ListOperatorsRecipe, Artifacts *tmp_Tab_Artifacts, int CurrentDebugLevel)
{
	if(CurrentDebugLevel >= 0)
	{
		// We assume that ListIDIntputRecipe and ListOperatorsRecipe cannot be empty, 
		// cause the model doesn't allow a recipe without input and operators.
		// If not, this control terminate application with a failure.
		if(ListIDIntputRecipe.size() <= 0)
		{
			cout << "Some error in parameter passed at CalcOutputThisRecipe function: list of input is empty -> " << ListIDIntputRecipe.size() << endl;
			exit(EXIT_FAILURE);
		}
		if(ListOperatorsRecipe.size() <= 0)
		{
			cout << "Some error in parameter passed at CalcOutputThisRecipe function: list of operators is empty -> " << ListOperatorsRecipe.size() << endl;
			exit(EXIT_FAILURE);
		}
	}
	list<Mil_Int>::iterator tmpListIDIntputRecipeIter = ListIDIntputRecipe.begin();
	Artifacts::iterator tmp_Tab_ArtifactsIter = tmp_Tab_Artifacts->find(*tmpListIDIntputRecipeIter);
	if((CurrentDebugLevel >= 0) && (tmp_Tab_ArtifactsIter == tmp_Tab_Artifacts->end()))
	{
		Mil_Int tmpIDInputToAnalize = *tmpListIDIntputRecipeIter;
		cout << "Some error in CalcOutputThisRecipe function: cannot find *tmpListInputRecipeIter in tmp_Tab_Artifacts: " << tmpIDInputToAnalize << endl;
		exit(EXIT_FAILURE);
	}
	
	Mil_Int tmpOutputRecipe = tmp_Tab_ArtifactsIter->second.GetName();
	list<Mil_Int>::iterator tmpListOperatorsRecipeIter = ListOperatorsRecipe.begin();
	for(++tmpListIDIntputRecipeIter; tmpListIDIntputRecipeIter != ListIDIntputRecipe.end(); tmpListIDIntputRecipeIter++)
	{
		tmp_Tab_ArtifactsIter = tmp_Tab_Artifacts->find(*tmpListIDIntputRecipeIter);
		Mil_Int tmpCurrentOperator = *tmpListOperatorsRecipeIter;
		if((CurrentDebugLevel >= 0) && (tmp_Tab_ArtifactsIter == tmp_Tab_Artifacts->end()))
		{
			Mil_Int tmpIDArtifactsToAnalize = *tmpListIDIntputRecipeIter;
			cout << "Error in CalcOutputThisRecipe function: cannot find the artifact ID" << tmpIDArtifactsToAnalize << endl;
			exit(EXIT_FAILURE);
		}
		tmpOutputRecipe = DoCalc(tmpOutputRecipe, tmp_Tab_ArtifactsIter->second.GetName(), tmpCurrentOperator);
		tmpListOperatorsRecipeIter++;
	}
	
	return(tmpOutputRecipe);
}

Mil_Int DoCalc(Mil_Int tmpFirstNum, Mil_Int tmpSecondNum, Mil_Int TypeOperator)
{
	Mil_Int Result = 0;
	switch (TypeOperator) 
	{
		case 1:
			Result = tmpFirstNum + tmpSecondNum;
			break;
		case 2:
			Result = tmpFirstNum - tmpSecondNum;
			break;
		case 3:
			Result = tmpFirstNum * tmpSecondNum;
			break;
		case 4:
			Result = tmpFirstNum / tmpSecondNum;
			break;
		case 5:
			Result = tmpFirstNum % tmpSecondNum;
			break;
		default:
		{
			cout << "Error in DoCalc function: TypeOperator passed doesn't exist: " << TypeOperator << endl;
			exit(EXIT_FAILURE);
		}
	}
	return(Result);
}

Mil_Int ValidateThisOutputRecipe(Mil_Int LowBoundary, Mil_Int HighBoundary, vector<Mil_Int> &VectValuesToCompare, Mil_Int RecipeOutputName, 
											Mil_Int tmpGoalToCompare, Agents *tmp_Current_TabAgents, Mil_Int tmp_CurrentIDAgentToAnalize, 
											MilinitParams &tmp_Current_InitParam, int tmp_Current_DebugLevel)
{
	// search agent's style for valide this recipe
	Agents::iterator tmp_Current_TabAgentsIter = tmp_Current_TabAgents->find(tmp_CurrentIDAgentToAnalize);
	if((tmp_Current_DebugLevel >= 0) && (tmp_Current_TabAgentsIter == tmp_Current_TabAgents->end()))
	{
		cout << "Error in ValidateThisOutputRecipe function: cannot find tmp_Current_TabAgentsIter in tmp_Current_TabAgents: " << tmp_CurrentIDAgentToAnalize << endl;
		exit(EXIT_FAILURE);
	}
	Mil_Int ValidateRecipeType = tmp_Current_TabAgentsIter->second.Style.GetValidateRecipeOutput();
	
	switch (ValidateRecipeType) {
	case 1:
		{
			// If output is out of the artifacts space, it will be change in ones of two boundaries.
			// Each output is valide into the artifacts space. 
			RecipeOutputName = AdjustOutputOnBoundary(RecipeOutputName, LowBoundary, HighBoundary);
		}
		break;
	case 2:
		{
			RecipeOutputName = AdjustOutputOnBoundary(RecipeOutputName, LowBoundary, HighBoundary);
			RecipeOutputName = CheckOutputCopiesThisAgent(RecipeOutputName, VectValuesToCompare);
		}
		break;
	case 3:
		{
			RecipeOutputName = InvalidateOutputOnBoundary(RecipeOutputName, LowBoundary, HighBoundary);
			RecipeOutputName = CheckOutputEqualRawMaterials(RecipeOutputName, tmp_Current_InitParam);
			RecipeOutputName = CheckOutputCopiesThisAgent(RecipeOutputName, VectValuesToCompare);
		}
		break;
	case 4:
		{
			RecipeOutputName = AdjustOutputOnBoundary(RecipeOutputName, LowBoundary, HighBoundary);
			RecipeOutputName = CheckOutputCopiesThisAgent(RecipeOutputName, VectValuesToCompare);

			if(tmpGoalToCompare != 0)
				RecipeOutputName = CheckOutputIntoGoalRange(RecipeOutputName, tmpGoalToCompare);
		}
		break;
	case 5:
		{
			RecipeOutputName = AdjustOutputOnTorus(RecipeOutputName, HighBoundary, LowBoundary);
			RecipeOutputName = CheckOutputCopiesThisAgent(RecipeOutputName, VectValuesToCompare);
			RecipeOutputName = CheckOutputEqualRawMaterials(RecipeOutputName, tmp_Current_InitParam);
		}
		break;
	case 6:
		{
			RecipeOutputName = AdjustOutputOnBoundary(RecipeOutputName, LowBoundary, HighBoundary);
			RecipeOutputName = CheckOutputEqualRawMaterials(RecipeOutputName, tmp_Current_InitParam);
			RecipeOutputName = CheckOutputCopiesThisAgent(RecipeOutputName, VectValuesToCompare);
			
			if(tmpGoalToCompare != 0)
				RecipeOutputName = CheckOutputIntoGoalRange(RecipeOutputName, tmpGoalToCompare);
		}
		break;
	case 7:
		{
			RecipeOutputName = AdjustOutputOnBoundary(RecipeOutputName, LowBoundary, HighBoundary);
			RecipeOutputName = CheckOutputEqualRawMaterials(RecipeOutputName, tmp_Current_InitParam);

			if(tmpGoalToCompare != 0)
				RecipeOutputName = CheckOutputIntoGoalRange(RecipeOutputName, tmpGoalToCompare);
		}
		break;
	case 8:
		{
			RecipeOutputName = AdjustOutputOnTorus(RecipeOutputName, HighBoundary, LowBoundary);			
			RecipeOutputName = CheckOutputEqualRawMaterials(RecipeOutputName, tmp_Current_InitParam);
		}
		break;
	default:
		break;
	}
	
	return(RecipeOutputName);
}

void InsertNewRecipe(MilinitParams &tmp_Init_Param, SystemParams &tmp_Milovo_Param, MilovoRandom &tmp_Current_MiloRand, Agents *tmp_Tab_Agents, Mil_Int tmp_CurrentIDAgentToCreate, 
							Recipes *tmp_Tab_Recipes, Artifacts *tmp_Tab_Artifacts, list<Mil_Int> &tmp_ListIDInput, list<Mil_Int> &tmp_ListOperators, 
							Mil_Int tmp_OutputThisRecipe, Mil_Int tmpAmountArtifact, Mil_Int tmpCurrentStep, int CurrentDebugLevel)
{
	// prepare data for recipe member variables
	Mil_Int tmp_Tab_Recipes_Size = tmp_Tab_Recipes->size();
	Recipes::iterator tmp_Tab_RecipesIter;
	Mil_Int tmpIDRecipeToCreate;
	if(tmp_Tab_Recipes_Size <= 0)
		tmpIDRecipeToCreate = tmp_Tab_Recipes->size() + 1;
	else
	{
		tmp_Tab_RecipesIter = tmp_Tab_Recipes->end();
		--tmp_Tab_RecipesIter;
		tmpIDRecipeToCreate = tmp_Tab_RecipesIter->second.GetID() + 1;
	}
	Mil_Int tmpIDAgentOwnerRecipeToCreate = tmp_CurrentIDAgentToCreate;
	Mil_Int tmpStatusRecipeToCreate = tmp_Milovo_Param.GetMaxLifeRecipes();
	// insert the new recipe into TabRecipe using its constructor
	tmp_Tab_Recipes->insert(make_pair(tmpIDRecipeToCreate, Recipe(tmpIDRecipeToCreate, tmpIDAgentOwnerRecipeToCreate, tmpStatusRecipeToCreate)));
	tmp_Tab_RecipesIter = tmp_Tab_Recipes->find(tmpIDRecipeToCreate);
	if((CurrentDebugLevel >= 0) && (tmp_Tab_RecipesIter == tmp_Tab_Recipes->end()))
	{
		cout << "Error in CreateInitRecipe function: Cannot find the IDRecipe already created" << endl;
		exit(EXIT_FAILURE);
	}
	// insert input of recipe in tmp_TabRecipes
	for(list<Mil_Int>::iterator tmp_ListIDInputIter = tmp_ListIDInput.begin(); tmp_ListIDInputIter != tmp_ListIDInput.end(); tmp_ListIDInputIter++)
	{
		tmp_Tab_RecipesIter->second.LinksIDArtifacts.push_back(*tmp_ListIDInputIter);
		// insert name input of recipe in tmp_TabRecipes
		Artifacts::iterator tmp_Tab_ArtifactsIter = tmp_Tab_Artifacts->find(*tmp_ListIDInputIter);
		tmp_Tab_RecipesIter->second.LinksNameArtifacts.push_back(tmp_Tab_ArtifactsIter->second.GetName());
	}
	// insert operator of recipe in tmp_TabRecipes			
	for(list<Mil_Int>::iterator tmp_ListOperatorsIter = tmp_ListOperators.begin(); tmp_ListOperatorsIter != tmp_ListOperators.end(); tmp_ListOperatorsIter++)
		tmp_Tab_RecipesIter->second.LinksOperators.push_back(*tmp_ListOperatorsIter);
	// insert the output of new recipe as a new artifact of TabArtifacts
	Artifacts::iterator tmp_Tab_ArtifactsIter = tmp_Tab_Artifacts->end();
	--tmp_Tab_ArtifactsIter;
	Mil_Int tmpIDArtifactToCreate = tmp_Tab_ArtifactsIter->second.GetID() + 1;
	Mil_Int tmpIDAgentOwnerArtifactToCreate = tmp_CurrentIDAgentToCreate;
	Mil_Int tmpStatusArtifactToCreate = tmp_Milovo_Param.GetMaxLifeArtifacts();
	Mil_Int tmpAmountArtifactCeil = tmp_Current_MiloRand.GetIntRandom(tmp_Milovo_Param.GetQuantityCeilStartRange(), tmp_Milovo_Param.GetQuantityCeilEndRange());
	tmp_Tab_Artifacts->insert(make_pair(tmpIDArtifactToCreate, Artifact(tmpIDArtifactToCreate, tmp_OutputThisRecipe, tmpIDRecipeToCreate, 
																							  tmpIDAgentOwnerArtifactToCreate, tmpStatusArtifactToCreate, 
																							  tmpAmountArtifact, tmpAmountArtifactCeil, 0, tmpCurrentStep)));
	// set the IDArtifactOutput of this new recipe
	tmp_Tab_RecipesIter->second.SetIDArtifactOutput(tmpIDArtifactToCreate);
	// insert link to This new recipe in the LinkRecipes of current agent
	Agents::iterator tmp_Tab_AgentsIter = tmp_Tab_Agents->find(tmp_CurrentIDAgentToCreate);
	if((CurrentDebugLevel >= 0) && (tmp_Tab_AgentsIter == tmp_Tab_Agents->end()))
	{
		cout << "Error in CreateInitRecipe function: Cannot find the tmpCurrentIDAgentToCreate passed" << endl;
		exit(EXIT_FAILURE);
	}
	tmp_Tab_AgentsIter->second.LinkRecipes.push_back(tmpIDRecipeToCreate);
}

void GetAgentsAlive(vector<Mil_Int> &tmpVectAgentsAlive, Agents *tmpTabAgents, int CurrentDebugLevel)
{
	if(CurrentDebugLevel >= 1)
		cout << "GetAgentsAlive [begin]" << endl;
	// clear the vector that will contain the ID list of agent still alive
	if(tmpVectAgentsAlive.size() > 0)
		tmpVectAgentsAlive.clear();
	
	for(Agents::iterator tmpTabAgentsIter = tmpTabAgents->begin(); tmpTabAgentsIter != tmpTabAgents->end(); tmpTabAgentsIter++)
	{
		tmpVectAgentsAlive.push_back(tmpTabAgentsIter->second.GetID());
		if(CurrentDebugLevel >= 2)
			cout << "AgentID: " << tmpTabAgentsIter->second.GetID() << " is still Alive" << endl;
	}
	
	if(CurrentDebugLevel >= 1)
		cout << "GetAgentsAlive [end]" << endl;
}

void KillThisRecipe(Mil_Int tmpIDRecipeToAnalize, Recipes *tmp_TabRecipes, Artifacts *tmp_TabArtifacts, Agents *tmp_TabAgents, int CurrentDebugLevel)
{
	if(CurrentDebugLevel >= 1)
		cout << "KillThisRecipe [begin]" << endl;
	
	Recipes::iterator tmp_TabRecipesIter = tmp_TabRecipes->find(tmpIDRecipeToAnalize);
	if(CurrentDebugLevel >= 2)
		cout << "Kill recipe ID: " << tmp_TabRecipesIter->second.GetID() << " [Begin]" << endl;
	// find the position of artifact output of the recipe to eliminate from TabArtifacts
	Artifacts::iterator tmp_TabArtifactsIter = tmp_TabArtifacts->find(tmp_TabRecipesIter->second.GetIDArtifactOutput());
	if(CurrentDebugLevel >= 2)
		cout << "Erase Artifact output ID: " << tmp_TabArtifactsIter->second.GetID() << "(" << tmp_TabRecipesIter->second.GetIDArtifactOutput() << ")" << endl;
	// eliminate artifact output
	tmp_TabArtifacts->erase(tmp_TabArtifactsIter);
	// find the link of this recipe in list of agents recipe in TabAgents
	Agents::iterator tmp_TabAgentsIter = tmp_TabAgents->find(tmp_TabRecipesIter->second.GetIDAgentOwner());
	if(CurrentDebugLevel >= 2)
		cout << "Erase link of agent: " << tmp_TabAgentsIter->second.GetID() << "(RecipeID: " << tmp_TabRecipesIter->second.GetID() << ")" << endl;
	// remove this link from agent list
	bool FlagFound = false;
	list<Mil_Int>::iterator LinkRecipesAgentIter = tmp_TabAgentsIter->second.LinkRecipes.begin();
	while((FlagFound == false) && (LinkRecipesAgentIter != tmp_TabAgentsIter->second.LinkRecipes.end()))
	{
		if(*LinkRecipesAgentIter == tmp_TabRecipesIter->second.GetID())
		{
			tmp_TabAgentsIter->second.LinkRecipes.erase(LinkRecipesAgentIter);
			FlagFound = true;
		}
		LinkRecipesAgentIter++;
	}
	// eliminate the recipe from TabRecipe
	tmp_TabRecipes->erase(tmp_TabRecipesIter);
	
	if(CurrentDebugLevel >= 2)
		cout << "Kill recipe ID: " << tmp_TabRecipesIter->second.GetID() << " [End]" << endl;

	if(CurrentDebugLevel >= 1)
		cout << "KillThisRecipe [begin]" << endl;
}

void ExtractListOutputThisAgent(list<Mil_Int> &tmpListOutputThisAgent, Mil_Int tmpIDAgentOwner, Agents *tmp_TabAgents, Recipes *tmp_TabRecipes, 
										  Artifacts * tmp_TabArtifacts, int tmpCurrentDebugLevel)
{
	Agents::iterator tmp_TabAgentsIter = tmp_TabAgents->find(tmpIDAgentOwner);
	if((tmpCurrentDebugLevel >= 0) && (tmp_TabAgentsIter == tmp_TabAgents->end()))
	{
		cout << "Error in ExtractListOutputThisAgent function: cannot find tmp_TabAgentsIter in TabAgents. tmpIDAgentOwner -> " << tmpIDAgentOwner << endl;
		exit(EXIT_FAILURE);
	}
	for(list<Mil_Int>::iterator LinkRecipesIter = tmp_TabAgentsIter->second.LinkRecipes.begin(); LinkRecipesIter != tmp_TabAgentsIter->second.LinkRecipes.end(); LinkRecipesIter++)
	{
		Recipes::iterator tmp_TabRecipesIter = tmp_TabRecipes->find(*LinkRecipesIter);
		if(tmp_TabRecipesIter != tmp_TabRecipes->end())
		{
			Artifacts::iterator tmp_TabArtifactsIter = tmp_TabArtifacts->find(tmp_TabRecipesIter->second.GetIDArtifactOutput());
			if(tmp_TabArtifactsIter != tmp_TabArtifacts->end())
				tmpListOutputThisAgent.push_back(tmp_TabArtifactsIter->second.GetID());
		}
	}
}

void ExtractVectIDArtifactsKnowedByThisAgent(vector<Mil_Int> &VectArtifactsKnowed, Mil_Int tmpIDAgentToAnalize, Agents *CurrentTabAgents, 
															Recipes *CurrentTabRecipes, Artifacts *CurrentTabArtifacts, int CurrentDebugLevel)
{
	Agents::iterator CurrentTabAgentsIter = CurrentTabAgents->find(tmpIDAgentToAnalize);
	if((CurrentDebugLevel >= 0) && (CurrentTabAgentsIter == CurrentTabAgents->end()))
	{
		cout << "Error in ExtractVectIDArtifactsKnowedByThisAgent function: cannot find CurrentTabAgentsIter in TabAgents. tmpIDAgentToAnalize -> " << tmpIDAgentToAnalize << endl;
		exit(EXIT_FAILURE);
	}
	// for every IDArtifact stored in LinkArtifactsKnowed by this agent check if exist
	for(list<Mil_Int>::iterator LinkArtifactsKnowedIter = CurrentTabAgentsIter->second.LinkArtifactsKnowed.begin(); LinkArtifactsKnowedIter != CurrentTabAgentsIter->second.LinkArtifactsKnowed.end(); LinkArtifactsKnowedIter++)
	{
		Artifacts::iterator CurrentTabArtifactsIter = CurrentTabArtifacts->find(*LinkArtifactsKnowedIter);
		if(CurrentTabArtifactsIter != CurrentTabArtifacts->end())
		{
			if(VectArtifactsKnowed.size() == 0)
				VectArtifactsKnowed.push_back(CurrentTabArtifactsIter->second.GetID());
			else
			{
				bool FlagFound = false;
				vector<Mil_Int>::iterator VectArtifactsKnowedIter = VectArtifactsKnowed.begin();
				while((FlagFound == false) && (VectArtifactsKnowedIter != VectArtifactsKnowed.end()))
				{
					Artifacts::iterator VectArtifactsKnowedIter_Name = CurrentTabArtifacts->find(*VectArtifactsKnowedIter);
					if((CurrentDebugLevel >= 0) && (VectArtifactsKnowedIter_Name == CurrentTabArtifacts->end()))
					{
						cout << "Error in ExtractVectIDArtifactsKnowedByThisAgent function: cannot find VectArtifactsKnowedIter_Name in TabArtifacts" << endl;
						exit(EXIT_FAILURE);
					}
					if(CurrentTabArtifactsIter->second.GetName() == VectArtifactsKnowedIter_Name->second.GetName())
						FlagFound = true;
					VectArtifactsKnowedIter++;
				}
				// if not found another artifact name equal to this, insert
				if(FlagFound == false)
					VectArtifactsKnowed.push_back(CurrentTabArtifactsIter->second.GetID());
			}
		}
	}
}

Mil_Int FindArtifactSubstitutePreferential(Artifacts *CurrentTabArtifacts, Agents *CurrentTabAgents, Recipes *CurrentTabRecipes, Mil_Int tmpIDRecipeToAnalize, Mil_Int tmpIDArtifactToSubstitute, 
										 Mil_Int tmpNameArtifactToSubstitute, Mil_Int tmpQuantityNeed, Mil_Int CurrentIDAgent, int CurrentDebugLevel)
{
	Agents::iterator CurrentTabAgentsIter = CurrentTabAgents->find(CurrentIDAgent);
	if((CurrentDebugLevel >= 0) && (CurrentTabAgentsIter == CurrentTabAgents->end()))
	{
		cout << "Error in FindArtifactSubstitute function: cannot find CurrentTabAgentsIter in TabAgents" << endl;
		exit(EXIT_FAILURE);
	}
	Mil_Int tmpIDArtifactSubstitutive = tmpIDArtifactToSubstitute;
	list<Mil_Int>::iterator LinkArtifactsKnowedIter = CurrentTabAgentsIter->second.LinkArtifactsKnowed.begin();
	bool FlagFound = false;
	while((FlagFound == false) && (LinkArtifactsKnowedIter != CurrentTabAgentsIter->second.LinkArtifactsKnowed.end()))
	{
		Artifacts::iterator CurrentTabArtifactsIter = CurrentTabArtifacts->find(*LinkArtifactsKnowedIter);
		if(CurrentDebugLevel >= 2)
			cout << "looking for IDArt " << CurrentTabArtifactsIter->second.GetID() << endl;
		if((CurrentTabArtifactsIter->second.GetID() != tmpIDArtifactToSubstitute) && 
			(CurrentTabArtifactsIter->second.GetName() == tmpNameArtifactToSubstitute) &&
			(CurrentTabArtifactsIter->second.GetStatus() > 0) &&
			(CurrentTabArtifactsIter->second.GetIDAgentOwner() != CurrentIDAgent))
		{
			Mil_Int HowManyCopyThisArtifactInRecipe = GetHowManyCopyThisArtifactInRecipe(CurrentTabArtifactsIter->second.GetID(), CurrentTabArtifacts, 
																				 tmpIDRecipeToAnalize, CurrentTabRecipes, CurrentDebugLevel);
			if(CurrentTabArtifactsIter->second.GetAmount() > HowManyCopyThisArtifactInRecipe)
			{
				tmpIDArtifactSubstitutive = CurrentTabArtifactsIter->second.GetID();
				FlagFound = true;
				if(CurrentDebugLevel >= 2)
					cout << "found IDArt: " << tmpIDArtifactSubstitutive << endl;
			}
		}
		LinkArtifactsKnowedIter++;
	}
	
	if(CurrentDebugLevel >= 2)
		cout << "return IDArt: " << tmpIDArtifactSubstitutive << endl;
	return(tmpIDArtifactSubstitutive);
}

Mil_Int FindArtifactSubstitute(Artifacts *CurrentTabArtifacts, Agents *CurrentTabAgents, Recipes *CurrentTabRecipes, Mil_Int tmpIDRecipeToAnalize, 
										 Mil_Int tmpIDArtifactToSubstitute, Mil_Int tmpNameArtifactToSubstitute, Mil_Int tmpQuantityNeed, 
										 Mil_Int CurrentIDAgent, MilovoRandom &CurrentMiloRand, int CurrentDebugLevel)
{
	Agents::iterator CurrentTabAgentsIter = CurrentTabAgents->find(CurrentIDAgent);
	if((CurrentDebugLevel >= 0) && (CurrentTabAgentsIter == CurrentTabAgents->end()))
	{
		cout << "Error in FindArtifactSubstitute function: cannot find CurrentTabAgentsIter in TabAgents" << endl;
		exit(EXIT_FAILURE);
	}
	Mil_Int tmpIDArtifactSubstitutive = tmpIDArtifactToSubstitute;
	vector<Mil_Int> VectIDArtifactsSubstitutive;
	for(list<Mil_Int>::iterator LinkArtifactsKnowedIter = CurrentTabAgentsIter->second.LinkArtifactsKnowed.begin(); LinkArtifactsKnowedIter != CurrentTabAgentsIter->second.LinkArtifactsKnowed.end(); LinkArtifactsKnowedIter++)
	{
		if(CurrentDebugLevel >= 2)
			cout << "Looking for IDArt: " << *LinkArtifactsKnowedIter << endl;
		
		Artifacts::iterator CurrentTabArtifactsIter = CurrentTabArtifacts->find(*LinkArtifactsKnowedIter);
		if((CurrentTabArtifactsIter != CurrentTabArtifacts->end()) && 
			(CurrentTabArtifactsIter->second.GetID() != tmpIDArtifactToSubstitute) && 
			(CurrentTabArtifactsIter->second.GetName() == tmpNameArtifactToSubstitute) &&
			(CurrentTabArtifactsIter->second.GetStatus() > 0) &&
			(CurrentTabArtifactsIter->second.GetIDAgentOwner() != CurrentIDAgent))
		{
			Mil_Int HowManyCopyThisArtifactInRecipe = GetHowManyCopyThisArtifactInRecipe(CurrentTabArtifactsIter->second.GetID(), CurrentTabArtifacts, 
																												  tmpIDRecipeToAnalize, CurrentTabRecipes, CurrentDebugLevel);
			if(CurrentTabArtifactsIter->second.GetAmount() > HowManyCopyThisArtifactInRecipe)
			{
				VectIDArtifactsSubstitutive.push_back(CurrentTabArtifactsIter->second.GetID());
				if(CurrentDebugLevel >= 2)
					cout << "found IDArt: " << tmpIDArtifactSubstitutive << endl;
			}
		}
	}	
	if(VectIDArtifactsSubstitutive.size() > 0)
		tmpIDArtifactSubstitutive = VectIDArtifactsSubstitutive[CurrentMiloRand.GetIntRandom(0, (VectIDArtifactsSubstitutive.size() - 1))];
	if(CurrentDebugLevel >= 2)
		cout << "return IDArt: " << tmpIDArtifactSubstitutive << endl;
	
	return(tmpIDArtifactSubstitutive);
}

Mil_Int FindArtifactSubstituteOld(Artifacts *CurrentTabArtifacts, Agents *CurrentTabAgents, Mil_Int tmpIDArtifactToSubstitute, 
							   Mil_Int tmpNameArtifactToSubstitute, Mil_Int tmpQuantityNeed, Mil_Int CurrentIDAgent, int CurrentDebugLevel)
{
	Agents::iterator CurrentTabAgentsIter = CurrentTabAgents->find(CurrentIDAgent);
	if((CurrentDebugLevel >= 0) && (CurrentTabAgentsIter == CurrentTabAgents->end()))
	{
		cout << "Error in FindArtifactSubstitute function: cannot find CurrentTabAgentsIter in TabAgents" << endl;
		exit(EXIT_FAILURE);
	}
	Mil_Int tmpIDArtifactSubstitutive = tmpIDArtifactToSubstitute;
	list<Mil_Int>::iterator LinkArtifactsKnowedIter = CurrentTabAgentsIter->second.LinkArtifactsKnowed.begin();
	bool FlagFound = false;
	while((FlagFound == false) && (LinkArtifactsKnowedIter != CurrentTabAgentsIter->second.LinkArtifactsKnowed.end()))
	{
		Artifacts::iterator CurrentTabArtifactsIter = CurrentTabArtifacts->find(*LinkArtifactsKnowedIter);
		if(CurrentDebugLevel >= 2)
			cout << "looking for IDArt " << CurrentTabArtifactsIter->second.GetID() << endl;
		if((CurrentTabArtifactsIter->second.GetID() != tmpIDArtifactToSubstitute) && 
		   (CurrentTabArtifactsIter->second.GetName() == tmpNameArtifactToSubstitute) &&
		   (CurrentTabArtifactsIter->second.GetAmount() > tmpQuantityNeed) &&
		   (CurrentTabArtifactsIter->second.GetStatus() > 0) &&
		   (CurrentTabArtifactsIter->second.GetIDAgentOwner() != CurrentIDAgent))
		{
			bool FlagRecipeCopyFound = false;
			list<Mil_Int>::iterator LinkRecipesIter = CurrentTabAgentsIter->second.LinkRecipes.begin();
			while((FlagRecipeCopyFound == false) && (LinkRecipesIter != CurrentTabAgentsIter->second.LinkRecipes.end()))
			{
				if(CurrentTabArtifactsIter->second.GetID() == *LinkRecipesIter)
					FlagRecipeCopyFound = true;
				else LinkRecipesIter++;
			}
			if(FlagRecipeCopyFound == false)
			{
				tmpIDArtifactSubstitutive = CurrentTabArtifactsIter->second.GetID();
				FlagFound = true;
				if(CurrentDebugLevel >= 2)
					cout << "found IDArt: " << tmpIDArtifactSubstitutive << endl;
			}
		}
		LinkArtifactsKnowedIter++;
	}
	
	if(CurrentDebugLevel >= 2)
		cout << "return IDArt: " << tmpIDArtifactSubstitutive << endl;
	return(tmpIDArtifactSubstitutive);
}

void KillThisAgent(Mil_Int CurrentIDAgent, Agents *CurrentTabAgents, Recipes *CurrentTabRecipes, Artifacts *CurrentTabArtifacts, int CurrentDebugLevel)
{
	Agents::iterator CurrentTabAgentsIter = CurrentTabAgents->find(CurrentIDAgent);
	if((CurrentDebugLevel >= 0) && (CurrentTabAgentsIter == CurrentTabAgents->end()))
	{
		cout << "Error in KillThisAgent function: cannot find CurrentTabAgentsIter in CurrentTabAgents" << endl;
		exit(EXIT_FAILURE);
	}
	if(CurrentDebugLevel >= 1)
		cout << "KillThisAgent [begin]" << endl;
	
	// Delete every agent's recipes
	list<Mil_Int>::iterator tmpIDLinkRecipeIter = CurrentTabAgentsIter->second.LinkRecipes.begin();
	while(tmpIDLinkRecipeIter != CurrentTabAgentsIter->second.LinkRecipes.end())
	{
		Recipes::iterator tmpTabRecipesIter = CurrentTabRecipes->find(*tmpIDLinkRecipeIter);
		Artifacts::iterator tmpTabArtifactsIter = CurrentTabArtifacts->find(tmpTabRecipesIter->second.GetIDArtifactOutput());
		tmpIDLinkRecipeIter++;
		KillThisRecipe(tmpTabRecipesIter->second.GetID(), CurrentTabRecipes, CurrentTabArtifacts, CurrentTabAgents, CurrentDebugLevel);
	}
	// delete relationship of this agent
	CurrentTabAgentsIter->second.TabRelationships.clear();
	// delete agent
	CurrentTabAgents->erase(CurrentTabAgentsIter);
	if(CurrentDebugLevel >= 2)
		cout << "Killing agent: " << CurrentIDAgent << endl;

	if(CurrentDebugLevel >= 1)
		cout << "KillThisAgent [end]" << endl;
}

void GenerateRelationshipThisAgent(Mil_Int tmp_IDAgentToAnalize, Agents *tmp_TabAgents, Recipes *tmp_TabRecipes, 
											  Artifacts *tmp_TabArtifacts, int CurrentStep, int tmp_DebugLevel)
{
	if(tmp_DebugLevel >= 2)
		cout << "GenerateRelationshipThisAgent [begin]" << endl;
	// extract the list of relationship of this agent
	ExtractIDAgentsKnowedByThisAgent(tmp_IDAgentToAnalize, tmp_TabAgents, tmp_TabRecipes, tmp_TabArtifacts, CurrentStep, tmp_DebugLevel);
	// extract the artifact list given by relationship of this agent
	ExtractIDArtifactsFromRelationshipsThisAgent(tmp_IDAgentToAnalize, tmp_TabAgents, tmp_TabRecipes, tmp_TabArtifacts, tmp_DebugLevel);
	if(tmp_DebugLevel >= 2)
	{
		Agents::iterator tmp_TabAgentsIter = tmp_TabAgents->find(tmp_IDAgentToAnalize);
		tmp_TabAgentsIter->second.PrintRelationship();
		tmp_TabAgentsIter->second.PrintArtifactsKnowed();
	}
	
	if(tmp_DebugLevel >= 2)
		cout << "GenerateRelationshipThisAgent [end]" << endl;
}

//void GenerateRelationshipThisAgentOld(SystemParams &tmp_MilovoParam, Mil_Int tmp_IDAgentToAnalize, Agents *tmp_TabAgents, Recipes *tmp_TabRecipes, 
//											  Artifacts *tmp_TabArtifacts, int tmp_DebugLevel)
//{
//	if(tmp_DebugLevel >= 2)
//		cout << "GenerateRelationshipThisAgent [begin]" << endl;
//	// extract the list of relationship of this agent
//	ExtractIDAgentsKnowedByThisAgent(tmp_IDAgentToAnalize, tmp_TabAgents, tmp_TabRecipes, tmp_TabArtifacts, tmp_DebugLevel);
//	// extract the artifact list given by relationship of this agent
//	ExtractIDArtifactsFromRelationshipsThisAgent(tmp_IDAgentToAnalize, tmp_TabAgents, tmp_TabRecipes, tmp_TabArtifacts, tmp_DebugLevel);
//	// calculate votes given to friends of this agent
//	CalcVotesThisAgent(tmp_IDAgentToAnalize, tmp_TabAgents, tmp_MilovoParam, tmp_DebugLevel);
//	if(tmp_DebugLevel >= 2)
//	{
//		Agents::iterator tmp_TabAgentsIter = tmp_TabAgents->find(tmp_IDAgentToAnalize);
//		tmp_TabAgentsIter->second.PrintRelationship();
//		tmp_TabAgentsIter->second.PrintArtifactsKnowed();
//	}
//	
//	if(tmp_DebugLevel >= 2)
//		cout << "GenerateRelationshipThisAgent [end]" << endl;
//}

void ExtractIDArtifactsFromRelationshipsThisAgent(Mil_Int tmpIDAgentToAnalize, Agents *tmpCurrentTabAgents, Recipes *tmpCurrentTabRecipes, 
																Artifacts *tmpCurrentTabArtifacts, int tmpCurrentDebugLevel)
{
	Agents::iterator tmpCurrentTabAgentsIter = tmpCurrentTabAgents->find(tmpIDAgentToAnalize);
	if((tmpCurrentDebugLevel >= 0) && (tmpCurrentTabAgentsIter == tmpCurrentTabAgents->end()))
	{
		cout << "Error in ExtractArtifactsFromRelationshipsThisAgent function: cannot find tmpCurrentTabAgentsIter in tmpCurrentTabAgents" << endl;
		exit(EXIT_FAILURE);
	}
	if(tmpCurrentDebugLevel >= 1)
		cout << "ExtractIDArtifactsFromRelationshipsThisAgent [begin]" << endl;
	
	tmpCurrentTabAgentsIter->second.LinkArtifactsKnowed.clear();
	for(Relationships::iterator TabRelationshipsIter = tmpCurrentTabAgentsIter->second.TabRelationships.begin(); TabRelationshipsIter != tmpCurrentTabAgentsIter->second.TabRelationships.end(); TabRelationshipsIter++)
	{
		if((tmpCurrentDebugLevel >= 0) && (TabRelationshipsIter->second.GetIDAgentPartner() == tmpIDAgentToAnalize))
		{
			cout << "Error in ExtractArtifactsFromRelationshipsThisAgent function: DAgentPartner is equal to tmpIDAgentToAnalize" << endl;
			exit(EXIT_FAILURE);
		}
		// if this agent knowed ZeroAgent there is a different searching path from friendship with others agents
		if(TabRelationshipsIter->second.GetIDAgentPartner() == 0)
		{
			bool FlagFindAllRawMaterials = false;
			Artifacts::iterator tmpCurrentTabArtifactsIter = tmpCurrentTabArtifacts->begin();
			while((FlagFindAllRawMaterials == false) && (tmpCurrentTabArtifactsIter != tmpCurrentTabArtifacts->end()))
			{
				if(tmpCurrentTabArtifactsIter->second.GetIDAgentOwner() == 0)
					tmpCurrentTabAgentsIter->second.LinkArtifactsKnowed.push_back(tmpCurrentTabArtifactsIter->second.GetID());
				else FlagFindAllRawMaterials = true;
				tmpCurrentTabArtifactsIter++;
			}
		}
		else
		{
			Agents::iterator tmpCurrentTabAgentsForNewPartnerIter = tmpCurrentTabAgents->find(TabRelationshipsIter->second.GetIDAgentPartner());
			if(tmpCurrentTabAgentsForNewPartnerIter != tmpCurrentTabAgents->end())
			{
				list<Mil_Int> ListOutputThisAgent;
				ExtractListOutputThisAgent(ListOutputThisAgent, TabRelationshipsIter->second.GetIDAgentPartner(), tmpCurrentTabAgents, tmpCurrentTabRecipes,
													tmpCurrentTabArtifacts, tmpCurrentDebugLevel);
				// if there are some IDArtifacts knowed
				if((tmpCurrentDebugLevel >= 0) && (ListOutputThisAgent.size() <= 0))
				{
					cout << "Error in ExtractArtifactsFromRelationshipsThisAgent function: there aren't artifacts knowed by agent: " << tmpIDAgentToAnalize << endl;
					exit(EXIT_FAILURE);
				}
				for(list<Mil_Int>::iterator ListOutputThisAgentIter = ListOutputThisAgent.begin(); ListOutputThisAgentIter != ListOutputThisAgent.end(); ListOutputThisAgentIter++)
				{
					Artifacts::iterator tmpCurrentTabArtifactsIter = tmpCurrentTabArtifacts->find(*ListOutputThisAgentIter);
					if(tmpCurrentTabArtifactsIter == tmpCurrentTabArtifacts->end())
					{
						cout << "Error in ExtractArtifactsFromRelationshipsThisAgent function: cannot find tmpCurrentTabArtifactsIter in tmpCurrentTabArtifacts" << endl;
						exit(EXIT_FAILURE);
					}
					if(tmpCurrentTabArtifactsIter->second.GetIDAgentOwner() == tmpIDAgentToAnalize)
					{
						cout << "Error in ExtractArtifactsFromRelationshipsThisAgent function: agent cannot use his output: " << tmpCurrentTabArtifactsIter->second.GetID() << endl;
						exit(EXIT_FAILURE);
					}
					tmpCurrentTabAgentsIter->second.LinkArtifactsKnowed.push_back(*ListOutputThisAgentIter);
				}
			}
		}
	}
	
	if(tmpCurrentDebugLevel >= 1)
		cout << "ExtractIDArtifactsFromRelationshipsThisAgent [end]" << endl;
}

void CalcVotesThisAgent(Mil_Int CurrentIDAgentToAnalize, Agents *CurrentTabAgents, SystemParams &CurrentMilovoParam, int CurrentDebugLevel)
{
	Agents::iterator CurrentTabAgentsIter = CurrentTabAgents->find(CurrentIDAgentToAnalize);
	if((CurrentDebugLevel >= 0) && (CurrentTabAgentsIter == CurrentTabAgents->end()))
	{
		cout << "Error in CalcVotesThisAgent function: cannot find CurrentTabAgentsIter in CurrentTabAgents: " << CurrentIDAgentToAnalize << endl;
		exit(EXIT_FAILURE);
	}
	if(CurrentDebugLevel >= 1)
		cout << "CalcVotesThisAgent [begin]" << endl;
	
	for(Relationships::iterator TabRelationshipsIter = CurrentTabAgentsIter->second.TabRelationships.begin(); TabRelationshipsIter != CurrentTabAgentsIter->second.TabRelationships.end(); TabRelationshipsIter++)
	{
		// firstly for Transactions
		Mil_Double tmpOldTransactions = TabRelationshipsIter->second.GetTransactions();
		Mil_Double tmpDeltaTransactions = TabRelationshipsIter->second.GetDeltaTransactions();
		Mil_Double tmpLambdaOldTransactions = CurrentTabAgentsIter->second.Style.GetLambdaTransactions() * tmpOldTransactions;
		Mil_Double tmpValueTransactionsForSigmaFunction = tmpOldTransactions + tmpDeltaTransactions - tmpLambdaOldTransactions;
		Mil_Double tmpNewTransactionsValue = CalcSigmaFunction(tmpValueTransactionsForSigmaFunction, CurrentMilovoParam, CurrentDebugLevel);
		if(CurrentDebugLevel >= 3)
		{
			cout << "tmpOldTransactions: " << tmpOldTransactions << endl;
			cout << "tmpDeltaTransactions: " << tmpDeltaTransactions << endl;
			cout << "tmpLambdaOldTransactions: " << tmpLambdaOldTransactions << endl;
			cout << "tmpValueTransactionsForSigmaFunction: " << tmpValueTransactionsForSigmaFunction << endl;
		}
		TabRelationshipsIter->second.SetTransactions(tmpNewTransactionsValue);
		TabRelationshipsIter->second.SetDeltaTransactions(0);
		// secondly for Projects
		Mil_Double tmpOldProjects = TabRelationshipsIter->second.GetProjects();
		Mil_Double tmpDeltaProjects = TabRelationshipsIter->second.GetDeltaProjects();
		Mil_Double tmpLambdaOldProjects = CurrentTabAgentsIter->second.Style.GetLambdaProjects() * tmpOldProjects;
		Mil_Double tmpValueProjectsForSigmaFunction = tmpOldProjects + tmpDeltaProjects - tmpLambdaOldProjects;
		Mil_Double tmpNewProjectsValue = CalcSigmaFunction(tmpValueProjectsForSigmaFunction, CurrentMilovoParam, CurrentDebugLevel);
		if(CurrentDebugLevel >= 3)
		{
			cout << "tmpOldProjects: " << tmpOldProjects << endl;
			cout << "tmpDeltaProjects: " << tmpDeltaProjects << endl;
			cout << "tmpLambdaOldProjects: " << tmpLambdaOldProjects << endl;
			cout << "tmpValueProjectsForSigmaFunction: " << tmpValueProjectsForSigmaFunction << endl;
		}
		TabRelationshipsIter->second.SetProjects(tmpNewProjectsValue);
		TabRelationshipsIter->second.SetDeltaProjects(0);
		// and then for Vote
		Mil_Double tmpAlphaTransactions = CurrentTabAgentsIter->second.Style.GetAlfaTransactions() * TabRelationshipsIter->second.GetTransactions();
		Mil_Double tmpBetaProjects = CurrentTabAgentsIter->second.Style.GetBetaProjects() * TabRelationshipsIter->second.GetProjects();
		Mil_Double tmpNewVoteValue = tmpAlphaTransactions + tmpBetaProjects;
		if(CurrentDebugLevel >= 3)
		{
			cout << "tmpAlphaTransactions: " << tmpAlphaTransactions << endl;
			cout << "tmpBetaProjects: " << tmpBetaProjects << endl;
			cout << "tmpNewVoteValue: " << tmpNewVoteValue << endl;
		}
		if(tmpNewVoteValue <= CurrentMilovoParam.GetEpsilonIfVoteZero())
			tmpNewVoteValue = CurrentMilovoParam.GetEpsilonIfVoteZero();
		TabRelationshipsIter->second.SetVote(tmpNewVoteValue);
	}

	if(CurrentDebugLevel >= 1)
		cout << "CalcVotesThisAgent [end]" << endl;
}

Mil_Double CalcSigmaFunction(Mil_Double tmpXValue, SystemParams &tmpCurrentMilovoParam, int tmpCurrentDebugLevel)
{	
	Mil_Double tmpYValue;
	if(tmpXValue < tmpCurrentMilovoParam.GetXsigmaMin())
	{
		tmpYValue = tmpCurrentMilovoParam.GetYsigmaMin();
		return(tmpYValue);
	}
	
	if(tmpXValue > tmpCurrentMilovoParam.GetXsigmaMax()) 
	{
		tmpYValue = tmpCurrentMilovoParam.GetYsigmaMax();
		return(tmpYValue);
	}
	
	Mil_Double tmp_a = (tmpCurrentMilovoParam.GetYsigmaMax() - tmpCurrentMilovoParam.GetYsigmaMin()) / (tmpCurrentMilovoParam.GetXsigmaMax() - tmpCurrentMilovoParam.GetXsigmaMin());
	Mil_Double tmp_b = ((tmpCurrentMilovoParam.GetYsigmaMin() * tmpCurrentMilovoParam.GetXsigmaMax()) - (tmpCurrentMilovoParam.GetYsigmaMax() * tmpCurrentMilovoParam.GetXsigmaMin())) / (tmpCurrentMilovoParam.GetXsigmaMax() - tmpCurrentMilovoParam.GetXsigmaMin());	
	tmpYValue = (tmp_a * tmpXValue) + tmp_b;
	
	return(tmpYValue);
}

void SetProjectTheseAgents(vector<Mil_Int> &tmpVectIDAgents, Agents *tmp_CurrentTabAgents, bool tmpFlagSuccessed, int tmp_CurrentDebugLevel)
{
	for(vector<Mil_Int>::iterator tmpVectIDAgentsIter = tmpVectIDAgents.begin(); tmpVectIDAgentsIter != tmpVectIDAgents.end(); tmpVectIDAgentsIter++)
	{
		for(vector<Mil_Int>::iterator tmpVectIDAgentsFriendIter = tmpVectIDAgents.begin(); tmpVectIDAgentsFriendIter != tmpVectIDAgents.end(); tmpVectIDAgentsFriendIter++)
		{
			if(tmpVectIDAgentsIter != tmpVectIDAgentsFriendIter)
			{
				Agents::iterator tmp_CurrentTabAgentsIter = tmp_CurrentTabAgents->find(*tmpVectIDAgentsIter);
				if((tmp_CurrentDebugLevel >= 0) && (tmp_CurrentTabAgentsIter == tmp_CurrentTabAgents->end()))
				{
					Mil_Int tmpIDAgentToAnalize = *tmpVectIDAgentsIter;
					cout << "Error in SetProjectSuccededTheseAgents function: cannot find tmp_CurrentTabAgentsIter in tmp_CurrentTabAgents: " << tmpIDAgentToAnalize << endl;
					exit(EXIT_FAILURE);
				}
				Relationships::iterator TabRelationshipsIter = tmp_CurrentTabAgentsIter->second.TabRelationships.find(*tmpVectIDAgentsFriendIter);
				if(TabRelationshipsIter != tmp_CurrentTabAgentsIter->second.TabRelationships.end())
				{
					if(tmpFlagSuccessed == true)
						TabRelationshipsIter->second.SetDeltaProjects(TabRelationshipsIter->second.GetDeltaProjects() + 
																					 tmp_CurrentTabAgentsIter->second.Style.GetValueSuccessedProjects());
					else TabRelationshipsIter->second.SetDeltaProjects(TabRelationshipsIter->second.GetDeltaProjects() - 
																						tmp_CurrentTabAgentsIter->second.Style.GetValueFailedProjects());
				}
				else 
				{
					if(tmpFlagSuccessed == true)
					{
						Mil_Int tmpIDAgentsNewFriendForProject = *tmpVectIDAgentsFriendIter;
						tmp_CurrentTabAgentsIter->second.TabRelationships.insert(make_pair(tmpIDAgentsNewFriendForProject, AgentRelationship(tmpIDAgentsNewFriendForProject)));
						Relationships::iterator TabRelationshipsNewFriendIter = tmp_CurrentTabAgentsIter->second.TabRelationships.find(tmpIDAgentsNewFriendForProject);
						if((tmp_CurrentDebugLevel >= 0) && (TabRelationshipsNewFriendIter == tmp_CurrentTabAgentsIter->second.TabRelationships.end()))
						{
							cout << "Error in SetProjectSuccededTheseAgents function: cannot find TabRelationshipsNewFriendIter in tmp_CurrentTabAgentsIter->second.TabRelationships" << endl;
							exit(EXIT_FAILURE);
						}
						TabRelationshipsNewFriendIter->second.SetDeltaProjects(TabRelationshipsIter->second.GetDeltaProjects() + 
																					 tmp_CurrentTabAgentsIter->second.Style.GetValueSuccessedProjects());
					}
				}
			}
		}
	}
}

void CheckOutputThisAgentToCompare(vector<Mil_Int> &CurrentVectToCompare, MilinitParams &tmp_CurrentInitParam, vector<Mil_Int> &CurrentVectIDAgentsToAnalize, 
											  Agents *tmp_CurrentTabAgents, Recipes *tmp_CurrentTabRecipes, Artifacts *tmp_CurrentTabArtifacts, int tmp_CurrentDebugLevel)
{
	if(tmp_CurrentDebugLevel >= 3)
		cout << "CheckOutputThisAgentToCompare [begin]" << endl;
	
	for(vector<Mil_Int>::iterator CurrentVectIDAgentsToAnalizeIter = CurrentVectIDAgentsToAnalize.begin(); CurrentVectIDAgentsToAnalizeIter != CurrentVectIDAgentsToAnalize.end(); CurrentVectIDAgentsToAnalizeIter++)
	{
		Mil_Int tmpIDAgentToAnalize = *CurrentVectIDAgentsToAnalizeIter;
		if(tmp_CurrentDebugLevel >= 3)
			cout << "IDAgent: " << tmpIDAgentToAnalize << endl;
		
		if(tmpIDAgentToAnalize > 0)
		{
			Agents::iterator tmp_CurrentTabAgentsIter = tmp_CurrentTabAgents->find(tmpIDAgentToAnalize);
			if((tmp_CurrentDebugLevel >= 0) && (tmp_CurrentTabAgentsIter == tmp_CurrentTabAgents->end()))
			{
				cout << "error in CheckOutputThisAgentToCompare function: cannot find tmp_CurrentTabAgentsIter in tmp_CurrentTabAgents: " << tmpIDAgentToAnalize << endl;
				exit(EXIT_FAILURE);
			}
			for(list<Mil_Int>::iterator LinkRecipesIter = tmp_CurrentTabAgentsIter->second.LinkRecipes.begin(); LinkRecipesIter != tmp_CurrentTabAgentsIter->second.LinkRecipes.end(); LinkRecipesIter++)
			{
				Recipes::iterator tmp_CurrentTabRecipesIter = tmp_CurrentTabRecipes->find(*LinkRecipesIter);
				if((tmp_CurrentDebugLevel >= 0) && (tmp_CurrentTabRecipesIter == tmp_CurrentTabRecipes->end()))
				{
					cout << "error in CheckOutputThisAgentToCompare function: cannot find tmp_CurrentTabRecipesIter in tmp_CurrentTabRecipes: " << tmp_CurrentTabRecipesIter->second.GetID() << endl;
					exit(EXIT_FAILURE);
				}
				Artifacts::iterator tmp_CurrentTabArtifactsIter = tmp_CurrentTabArtifacts->find(tmp_CurrentTabRecipesIter->second.GetIDArtifactOutput());
				if((tmp_CurrentDebugLevel >= 0) && (tmp_CurrentTabArtifactsIter == tmp_CurrentTabArtifacts->end()))
				{
					cout << "error in CheckOutputThisAgentToCompare function: cannot find tmp_CurrentTabArtifactsIter in tmp_CurrentTabArtifacts: " << tmp_CurrentTabArtifactsIter->second.GetID() << endl;
					exit(EXIT_FAILURE);
				}
				CurrentVectToCompare.push_back(tmp_CurrentTabArtifactsIter->second.GetName());
			}
		}
	}

	Agents::iterator tmp_CurrentTabAgentsIter = tmp_CurrentTabAgents->find(CurrentVectIDAgentsToAnalize[0]);
	if((tmp_CurrentDebugLevel >= 0) && (tmp_CurrentTabAgentsIter == tmp_CurrentTabAgents->end()))
	{
		cout << "error in CheckOutputThisAgentToCompare function: cannot find tmp_CurrentTabAgentsIter in tmp_CurrentTabAgents: " << CurrentVectIDAgentsToAnalize[0] << endl;
		exit(EXIT_FAILURE);
	}
	if(tmp_CurrentTabAgentsIter->second.Style.GetValidateRecipeOutput() == 3)
	{
		for(vector<Mil_Int>::iterator RawMaterialIter = tmp_CurrentInitParam.VectRawMaterials.begin(); RawMaterialIter != tmp_CurrentInitParam.VectRawMaterials.end(); RawMaterialIter++)
			CurrentVectToCompare.push_back(*RawMaterialIter);
	}
	
	if(tmp_CurrentDebugLevel >= 3)
	{
		for(vector<Mil_Int>::iterator CurrentVectToCompareIter = CurrentVectToCompare.begin(); CurrentVectToCompareIter != CurrentVectToCompare.end(); CurrentVectToCompareIter++)
		{
			Mil_Int tmpIDArtifactToPrint = *CurrentVectToCompareIter;
			cout << "Name to Compare: " << tmpIDArtifactToPrint << endl;
		}
		cout << "CheckOutputThisAgentToCompare [end]" << endl;
	}
}

void ExtractIDAgentsKnowedByThisAgent(Mil_Int CurrentIDAgentToAnalize, Agents *CurrentTabAgents, Recipes *CurrentTabRecipes, 
												  Artifacts *CurrentTabArtifacts, int tmpCurrentStep, int CurrentDebugLevel)
{
	// read every recipe of this agent
	Agents::iterator CurrentTabAgentsIter = CurrentTabAgents->find(CurrentIDAgentToAnalize);
	if((CurrentDebugLevel >= 0) && (CurrentTabAgentsIter == CurrentTabAgents->end()))
	{
		cout << "Error in ExtractIDAgentsKnowedByThisAgent function: cannot find CurrentTabAgentsIter in CurrentTabAgents" << endl;
		exit(EXIT_FAILURE);
	}
	if(CurrentDebugLevel >= 1)
		cout << "ExtractIDAgentsKnowedByThisAgent [begin]" << endl;
	// for each recipe of this agent, we looking for every owner of input artifact, and
	// insert it into agent's relationship table.
	vector<Mil_Int> VectFriendsThisAgent;
	ExtractCurrentFriendsThisAgent(VectFriendsThisAgent, CurrentIDAgentToAnalize, CurrentTabAgents, CurrentTabRecipes, 
											 CurrentTabArtifacts, CurrentDebugLevel);
	// check if this agent if already a friend of current agent
	AddNewFriendsThisAgent(VectFriendsThisAgent, CurrentIDAgentToAnalize, CurrentTabAgents, CurrentTabRecipes, 
								  CurrentTabArtifacts, CurrentDebugLevel);
	DeleteOldFriendsThisAgents(VectFriendsThisAgent, CurrentIDAgentToAnalize, CurrentTabAgents, CurrentTabRecipes, 
										CurrentTabArtifacts, tmpCurrentStep, CurrentDebugLevel);
	// if GetHowManyNewFriends = -1 agent must know all others agents
	if(CurrentTabAgentsIter->second.Style.GetHowManyNewFriends() == -1)
	{
		CurrentTabAgentsIter->second.TabRelationships.clear();
		for(Agents::iterator tmpCurrentTabAgentsIter = CurrentTabAgents->begin(); tmpCurrentTabAgentsIter != CurrentTabAgents->end(); tmpCurrentTabAgentsIter++)
		{
			if(tmpCurrentTabAgentsIter->second.GetID() != CurrentTabAgentsIter->second.GetID())
				CurrentTabAgentsIter->second.TabRelationships.insert(make_pair(tmpCurrentTabAgentsIter->second.GetID(), AgentRelationship(tmpCurrentTabAgentsIter->second.GetID())));
		}
		// insert earth Agent
		CurrentTabAgentsIter->second.TabRelationships.insert(make_pair(0, AgentRelationship(0)));
				
	}	
	// if style of this agent wants insert new relationship
	if(CurrentTabAgentsIter->second.Style.GetHowManyNewFriends() > 0)
	{
		vector<Mil_Int> VectIDAgentsNotKnowedByThisAgent;
		// Check for new relationships. Reading agents table and skipping agents already knowed
		for(Agents::iterator tmpCurrentTabAgentsIter = CurrentTabAgents->begin(); tmpCurrentTabAgentsIter != CurrentTabAgents->end(); tmpCurrentTabAgentsIter++)
		{
			if(tmpCurrentTabAgentsIter->second.GetID() != CurrentTabAgentsIter->second.GetID())
			{
				bool FlagFriendFound = false;
				Relationships::iterator TabRelationshipsIter = CurrentTabAgentsIter->second.TabRelationships.begin();
				while((FlagFriendFound == false) && (TabRelationshipsIter != CurrentTabAgentsIter->second.TabRelationships.end()))
				{
					if(tmpCurrentTabAgentsIter->second.GetID() == TabRelationshipsIter->second.GetIDAgentPartner())
						FlagFriendFound = true;
					TabRelationshipsIter++;
				}
				if(FlagFriendFound == false)
					VectIDAgentsNotKnowedByThisAgent.push_back(tmpCurrentTabAgentsIter->second.GetID());
			}
		}
		// if this agent is allowed to know ZeroAgent
		if(CurrentTabAgentsIter->second.Style.GetIncludeZeroAgentInNewFriends() == 1)
			VectIDAgentsNotKnowedByThisAgent.push_back(0);
		// if not empty, add new acquitance at this agent
		if(VectIDAgentsNotKnowedByThisAgent.empty() == false)
		{
			random_shuffle(VectIDAgentsNotKnowedByThisAgent.begin(), VectIDAgentsNotKnowedByThisAgent.end());
			vector<Mil_Int>::iterator VectIDAgentsNotKnowedByThisAgentIter = VectIDAgentsNotKnowedByThisAgent.begin();
			Mil_Int HowManyNewFriendsIndex = 0;
			while((HowManyNewFriendsIndex < CurrentTabAgentsIter->second.Style.GetHowManyNewFriends()) && (VectIDAgentsNotKnowedByThisAgentIter != VectIDAgentsNotKnowedByThisAgent.end()))
			{
				Mil_Int tmpIDNewAgentForRelationship = *VectIDAgentsNotKnowedByThisAgentIter;
				CurrentTabAgentsIter->second.TabRelationships.insert(make_pair(tmpIDNewAgentForRelationship, AgentRelationship(tmpIDNewAgentForRelationship)));
				VectIDAgentsNotKnowedByThisAgentIter++;
				HowManyNewFriendsIndex++;
			}
		}
	}
	
	if(CurrentDebugLevel >= 1)
		cout << "ExtractIDAgentsKnowedByThisAgent [end]" << endl;	
}

void ExtractCurrentFriendsThisAgent(vector<Mil_Int> &tmpVectFriendsThisAgent, Mil_Int tmpCurrentIDAgentToAnalize, Agents *tmpCurrentTabAgents, 
												Recipes *tmpCurrentTabRecipes, Artifacts *tmpCurrentTabArtifacts, int tmpCurrentDebugLevel)
{
	Agents::iterator tmpCurrentTabAgentsIter = tmpCurrentTabAgents->find(tmpCurrentIDAgentToAnalize);
	if((tmpCurrentDebugLevel >= 0) && (tmpCurrentTabAgentsIter == tmpCurrentTabAgents->end()))
	{
		cout << "Error in ExtractCurrentFriendsThisAgent function: cannot find tmpCurrentTabAgentsIter in tmpCurrentTabAgents" << tmpCurrentIDAgentToAnalize << endl;
		exit(EXIT_FAILURE);
	}
	// extract each output of this agent's recipes and check for agent owner of each of them.
	for(list<Mil_Int>::iterator LinkRecipesIter = tmpCurrentTabAgentsIter->second.LinkRecipes.begin(); LinkRecipesIter != tmpCurrentTabAgentsIter->second.LinkRecipes.end(); LinkRecipesIter++)
	{
		if(tmpCurrentDebugLevel >= 2)
		{
			Mil_Int tmpIDRecipeToPrint = *LinkRecipesIter;
			cout << "searching for IDRecipe: " << tmpIDRecipeToPrint << endl;
		}
		Recipes::iterator tmpCurrentTabRecipesIter = tmpCurrentTabRecipes->find(*LinkRecipesIter);
		if((tmpCurrentDebugLevel >= 0) && (tmpCurrentTabRecipesIter == tmpCurrentTabRecipes->end()))
		{
			cout << "Error in ExtractCurrentFriendsThisAgent function: cannot find tmpCurrentTabRecipesIter in tmpCurrentTabRecipes" << tmpCurrentIDAgentToAnalize << endl;
			exit(EXIT_FAILURE);
		}
		if(tmpCurrentDebugLevel >= 2)
			cout << "found existing IDRecipe: " << tmpCurrentTabRecipesIter->second.GetID() << endl;
		for(list<Mil_Int>::iterator LinksIDArtifactsIter = tmpCurrentTabRecipesIter->second.LinksIDArtifacts.begin(); LinksIDArtifactsIter != tmpCurrentTabRecipesIter->second.LinksIDArtifacts.end(); LinksIDArtifactsIter++)
		{
			if(tmpCurrentDebugLevel >= 2)
			{
				Mil_Int tmpIDArtifactToPrint = *LinksIDArtifactsIter;
				cout << "searching for IDArtifact: " << tmpIDArtifactToPrint << " of IDRecipe: " << tmpCurrentTabRecipesIter->second.GetID() << endl;
			}
			// check if this artifact exist
			Artifacts::iterator tmpCurrentTabArtifactsIter = tmpCurrentTabArtifacts->find(*LinksIDArtifactsIter);
			if(tmpCurrentTabArtifactsIter != tmpCurrentTabArtifacts->end())
			{
				if(tmpCurrentDebugLevel >= 2)
					cout << "found existing IDArtifact: " << tmpCurrentTabArtifactsIter->second.GetID() << endl;
				// take the agent owner this artifact
				Mil_Int tmpIDAgentOwnerThisArtifact = tmpCurrentTabArtifactsIter->second.GetIDAgentOwner();
				if((tmpCurrentDebugLevel >= 0) && (tmpIDAgentOwnerThisArtifact == tmpCurrentIDAgentToAnalize))
				{
					cout << "Error in ExtractIDAgentsKnowedByThisAgent function: tmpIDAgentOwnerThisArtifact (" << tmpIDAgentOwnerThisArtifact <<
					") is equal to CurrentIDAgentToAnalize (" << tmpCurrentIDAgentToAnalize << ") ... No agent may use his outputs" << endl;
					exit(EXIT_FAILURE);
				}
				// check if this agent if already a friend of current agent
				tmpVectFriendsThisAgent.push_back(tmpIDAgentOwnerThisArtifact);
			}
		}
	}
}

void AddNewFriendsThisAgent(vector<Mil_Int> &tmpVectFriendsThisAgent, Mil_Int tmpCurrentIDAgentToAnalize, Agents *tmpCurrentTabAgents, 
							  Recipes *tmpCurrentTabRecipes, Artifacts *tmpCurrentTabArtifacts, int tmpCurrentDebugLevel)
{
	Agents::iterator tmpCurrentTabAgentsIter = tmpCurrentTabAgents->find(tmpCurrentIDAgentToAnalize);
	if((tmpCurrentDebugLevel >= 0) && (tmpCurrentTabAgentsIter == tmpCurrentTabAgents->end()))
	{
		cout << "Error in AddNewFriendsThisAgent function: cannot find tmpCurrentTabAgentsIter in tmpCurrentTabAgents" << tmpCurrentIDAgentToAnalize << endl;
		exit(EXIT_FAILURE);
	}
	for(vector<Mil_Int>::iterator tmpVectFriendsThisAgentIter = tmpVectFriendsThisAgent.begin(); tmpVectFriendsThisAgentIter != tmpVectFriendsThisAgent.end(); tmpVectFriendsThisAgentIter++)
	{
		Mil_Int tmpIDAgentsupplier = *tmpVectFriendsThisAgentIter;
		bool FlagFriendFound = false;
		Relationships::iterator TabRelationshipsIter = tmpCurrentTabAgentsIter->second.TabRelationships.begin();
		while((FlagFriendFound == false) && (TabRelationshipsIter != tmpCurrentTabAgentsIter->second.TabRelationships.end()))
		{
			if(tmpCurrentDebugLevel >= 2)
				cout << "searching IDAgent: " << tmpIDAgentsupplier << " in TabRelationships: " << TabRelationshipsIter->second.GetIDAgentPartner() << endl;
			
			if(tmpIDAgentsupplier == TabRelationshipsIter->second.GetIDAgentPartner())
				FlagFriendFound = true;
			TabRelationshipsIter++;
		}
		// if FlagFriendFound == false, this agent may be insert
		if(FlagFriendFound == false)
		{
			if(tmpCurrentDebugLevel >= 2)
				cout << "insert IDAgent:" << tmpIDAgentsupplier << " in TabRelationships of Agent: " << tmpCurrentTabAgentsIter->second.GetID() << endl;
			
			tmpCurrentTabAgentsIter->second.TabRelationships.insert(make_pair(tmpIDAgentsupplier, AgentRelationship(tmpIDAgentsupplier)));
		}
	}
}

void DeleteOldFriendsThisAgents(vector<Mil_Int> &tmpVectFriendsThisAgent, Mil_Int tmpCurrentIDAgentToAnalize, Agents *tmpCurrentTabAgents, 
										  Recipes *tmpCurrentTabRecipes, Artifacts *tmpCurrentTabArtifacts, int tmp_CurrentStep, 
										  int tmpCurrentDebugLevel)
{
	Agents::iterator tmpCurrentTabAgentsIter = tmpCurrentTabAgents->find(tmpCurrentIDAgentToAnalize);
	if((tmpCurrentDebugLevel >= 0) && (tmpCurrentTabAgentsIter == tmpCurrentTabAgents->end()))
	{
		cout << "Error in AddNewFriendsThisAgent function: cannot find tmpCurrentTabAgentsIter in tmpCurrentTabAgents" << tmpCurrentIDAgentToAnalize << endl;
		exit(EXIT_FAILURE);
	}
	Relationships::iterator TabRelationshipsIter = tmpCurrentTabAgentsIter->second.TabRelationships.begin();
	while(TabRelationshipsIter != tmpCurrentTabAgentsIter->second.TabRelationships.end())
	{
		bool FlagFriendFound = false;
		vector<Mil_Int>::iterator tmpVectFriendsThisAgentIter = tmpVectFriendsThisAgent.begin();
		while((FlagFriendFound == false) && (tmpVectFriendsThisAgentIter != tmpVectFriendsThisAgent.end()))
		{
			Mil_Int tmpIDAgentFriendToCompare = *tmpVectFriendsThisAgentIter;
			// check for IDAgentPartener in TabAgents
			Agents::iterator tmpCurrentIDAgentPartenerIter = tmpCurrentTabAgents->find(TabRelationshipsIter->second.GetIDAgentPartner());
			if((TabRelationshipsIter->second.GetIDAgentPartner() == tmpIDAgentFriendToCompare) || 
				(TabRelationshipsIter->second.GetProjects() > tmpCurrentTabAgentsIter->second.Style.GetProjectsDeadLevel()) ||
				(TabRelationshipsIter->second.GetDeltaProjects() > 0) || 
				((tmpCurrentIDAgentPartenerIter->second.GetBornStep() + TabRelationshipsIter->second.GetKnowledgeDecay()) > tmp_CurrentStep))
				FlagFriendFound = true;
			tmpVectFriendsThisAgentIter++;
		}
		
		if((FlagFriendFound == false) || 
			((tmpCurrentTabAgents->find(TabRelationshipsIter->second.GetIDAgentPartner()) == tmpCurrentTabAgents->end()) &&
			 (TabRelationshipsIter->second.GetIDAgentPartner() != 0)))
		{
			Relationships::iterator TabRelationshipsToDeleteIter = TabRelationshipsIter;
			TabRelationshipsIter++;
			tmpCurrentTabAgentsIter->second.TabRelationships.erase(TabRelationshipsToDeleteIter);
		}
		else TabRelationshipsIter++;
	}
}

void DeleteRecipesWithLessArtifactsStatus(Mil_Int tmpCurrentIDAgent, Agents *tmpCurrentTabAgents, Recipes *tmpCurrentTabRecipes, 
														Artifacts *tmpCurrentTabArtifacts, int tmpCurrentDebugLevel)
{
	Agents::iterator tmpCurrentTabAgentsIter = tmpCurrentTabAgents->find(tmpCurrentIDAgent);
	if((tmpCurrentDebugLevel >= 0) && (tmpCurrentTabAgentsIter == tmpCurrentTabAgents->end()))
	{
		cout << "Error in DeleteRecipesWithLessArtifactsStatus function: cannot find tmpCurrentTabAgentsIter in tmpCurrentTabAgents: " << tmpCurrentIDAgent << endl;
		exit(EXIT_FAILURE);
	}
	Mil_Int NumRecipeThisAgents = 0;

	for(list<Mil_Int>::iterator LinkRecipesIter = tmpCurrentTabAgentsIter->second.LinkRecipes.begin(); LinkRecipesIter != tmpCurrentTabAgentsIter->second.LinkRecipes.end(); LinkRecipesIter++)
	{
		Recipes::iterator tmpCurrentTabRecipesIter = tmpCurrentTabRecipes->find(*LinkRecipesIter);
		if(tmpCurrentTabRecipesIter != tmpCurrentTabRecipes->end())
			NumRecipeThisAgents++;
	}
	
	while(NumRecipeThisAgents >= tmpCurrentTabAgentsIter->second.Style.GetMaxRecipesAllowed())
	{
		Mil_Int tmpMinStatus = -1;
		Mil_Int tmpIDRecipeWithLessArtifactStatus = -1;
		for(list<Mil_Int>::iterator LinkRecipesIter = tmpCurrentTabAgentsIter->second.LinkRecipes.begin(); LinkRecipesIter != tmpCurrentTabAgentsIter->second.LinkRecipes.end(); LinkRecipesIter++)
		{
			Recipes::iterator tmpCurrentTabRecipesIter = tmpCurrentTabRecipes->find(*LinkRecipesIter);
			if(tmpCurrentTabRecipesIter != tmpCurrentTabRecipes->end())
			{
				Artifacts::iterator tmpCurrentTabArtifactsIter = tmpCurrentTabArtifacts->find(tmpCurrentTabRecipesIter->second.GetIDArtifactOutput());
				if((tmpMinStatus == -1) || (tmpCurrentTabArtifactsIter->second.GetStatus() < tmpMinStatus))
				{
					tmpIDRecipeWithLessArtifactStatus = tmpCurrentTabRecipesIter->second.GetID();
					tmpMinStatus = tmpCurrentTabArtifactsIter->second.GetStatus();
				}
			}
		}	
		
		KillThisRecipe(tmpIDRecipeWithLessArtifactStatus, tmpCurrentTabRecipes, tmpCurrentTabArtifacts, tmpCurrentTabAgents, tmpCurrentDebugLevel);
		NumRecipeThisAgents--;
	}
}

bool AddScaffoldingFriends(Mil_Int tmpCurrentIDAgentToAnalize, Agents *tmpCurrentTabAgents, ScaffoldingStructure *tmpCurrentTabScaffoldingStructure, 
									int tmpCurrentDebugLevel)
{
	Agents::iterator tmpCurrentTabAgentsIter = tmpCurrentTabAgents->find(tmpCurrentIDAgentToAnalize);
	if((tmpCurrentDebugLevel >= 0) && (tmpCurrentTabAgentsIter == tmpCurrentTabAgents->end()))
	{
		cout << "Error in AddScaffoldingFriends function: cannot find tmpCurrentTabAgentsIter in tmpCurrentTabAgents: " << tmpCurrentIDAgentToAnalize << endl;
		exit(EXIT_FAILURE);
	}

	if(tmpCurrentDebugLevel >= 2)
		cout << "AddScaffoldingFriends [begin]" << endl;
	
	bool FlagCanSubscribe = false;
	ScaffoldingStructure::iterator tmpCurrentTabScaffoldingStructureIter = tmpCurrentTabScaffoldingStructure->begin();
	vector<Mil_Int> VectAgentsNotKnowed;
	while(tmpCurrentTabScaffoldingStructureIter != tmpCurrentTabScaffoldingStructure->end())
	{
		if(tmpCurrentDebugLevel >= 2)
			cout << "IDAgentScaffold: " << tmpCurrentTabScaffoldingStructureIter->second.GetIDAgent() << " [begin]" << endl;
		
		Relationships::iterator TabRelationshipsIter = tmpCurrentTabAgentsIter->second.TabRelationships.begin();
		bool FlagFound = false;
		while((FlagFound == false) && (TabRelationshipsIter != tmpCurrentTabAgentsIter->second.TabRelationships.end()))
		{
			if((TabRelationshipsIter->second.GetIDAgentPartner() == tmpCurrentTabScaffoldingStructureIter->second.GetIDAgent()) ||
				(tmpCurrentTabScaffoldingStructureIter->second.GetIDAgent() == tmpCurrentIDAgentToAnalize))
				FlagFound = true;
			else TabRelationshipsIter++;
		}
		if(FlagFound == false)
			VectAgentsNotKnowed.push_back(tmpCurrentTabScaffoldingStructureIter->second.GetIDAgent());

		if(tmpCurrentDebugLevel >= 2)
			cout << "IDAgentScaffold: " << tmpCurrentTabScaffoldingStructureIter->second.GetIDAgent() << " [end]" << endl;
		
		tmpCurrentTabScaffoldingStructureIter++;
	}
	
	if(VectAgentsNotKnowed.size() >= tmpCurrentTabAgentsIter->second.Style.GetAcceptScaffMinLevel())
	{
		FlagCanSubscribe = true;
		for(vector<Mil_Int>::iterator VectAgentsNotKnowedIter = VectAgentsNotKnowed.begin(); VectAgentsNotKnowedIter != VectAgentsNotKnowed.end(); VectAgentsNotKnowedIter++)
		{
			tmpCurrentTabScaffoldingStructureIter = tmpCurrentTabScaffoldingStructure->find(*VectAgentsNotKnowedIter);
			if((tmpCurrentDebugLevel >= 0) && (tmpCurrentTabScaffoldingStructureIter == tmpCurrentTabScaffoldingStructure->end()))
			{
				cout << "Error in AddScaffoldingFriends function: cannot find tmpCurrentTabScaffoldingStructureIter in tmpCurrentTabScaffoldingStructure" << endl;
				exit(EXIT_FAILURE);
			}
			tmpCurrentTabAgentsIter->second.TabRelationships.insert(make_pair(tmpCurrentTabScaffoldingStructureIter->second.GetIDAgent(), 
																									AgentRelationship(tmpCurrentTabScaffoldingStructureIter->second.GetIDAgent())));
		}
	}
	
	if(tmpCurrentDebugLevel >= 2)
		cout << "AddScaffoldingFriends [end]" << endl;

	return(FlagCanSubscribe);
}

void SubscribeThisAgent(Mil_Int tmpCurrentIDAgentToAnalize, ScaffoldingStructure *tmpCurrentTabScaffoldingStructure, 
								Mil_Int tmpScaffoldingMaxLevel, MilovoRandom &tmpCurrentMiloRand, int tmpCurrentDebugLevel)
{
	if(tmpCurrentDebugLevel >= 2)
		cout << "SubscribeThisAgent [begin]" << endl;
	
	bool FlagFound = false;
	ScaffoldingStructure::iterator tmpCurrentTabScaffoldingStructureIter = tmpCurrentTabScaffoldingStructure->begin();
	Mil_Int OldestScaffoldElement = tmpCurrentTabScaffoldingStructureIter->second.GetIDAgent();
	Mil_Int MaxScaffoldCounter = tmpCurrentTabScaffoldingStructureIter->second.GetCounter();
	
	vector<Mil_Int> VectOldScaffoldElements;
	while((FlagFound == false) && (tmpCurrentTabScaffoldingStructureIter != tmpCurrentTabScaffoldingStructure->end()))
	{
		if(tmpCurrentTabScaffoldingStructureIter->second.GetIDAgent() == tmpCurrentIDAgentToAnalize)
		{
			tmpCurrentTabScaffoldingStructureIter->second.ZeroCounter();
			FlagFound = true;
		}
		else
		{
			if(MaxScaffoldCounter < tmpCurrentTabScaffoldingStructureIter->second.GetCounter())
			{
				VectOldScaffoldElements.clear();
				OldestScaffoldElement = tmpCurrentTabScaffoldingStructureIter->second.GetIDAgent();
				MaxScaffoldCounter = tmpCurrentTabScaffoldingStructureIter->second.GetCounter();
				VectOldScaffoldElements.push_back(OldestScaffoldElement);
			}
			else
			{
				if(MaxScaffoldCounter == tmpCurrentTabScaffoldingStructureIter->second.GetCounter())
				{
					OldestScaffoldElement = tmpCurrentTabScaffoldingStructureIter->second.GetIDAgent();
					MaxScaffoldCounter = tmpCurrentTabScaffoldingStructureIter->second.GetCounter();
					VectOldScaffoldElements.push_back(OldestScaffoldElement);
				}
			}
		}	
		tmpCurrentTabScaffoldingStructureIter++;
	}
	
	if(FlagFound == false)
	{
		if(tmpCurrentTabScaffoldingStructure->size() >= tmpScaffoldingMaxLevel)
		{
			Mil_Int tmpOldScaffoldSelected = VectOldScaffoldElements[tmpCurrentMiloRand.GetIntRandom(0, (VectOldScaffoldElements.size() - 1))];
			ScaffoldingStructure::iterator tmpOldScaffoldElementIterToDelete = tmpCurrentTabScaffoldingStructure->find(tmpOldScaffoldSelected);
			if((tmpCurrentDebugLevel >= 1) && (tmpOldScaffoldElementIterToDelete == tmpCurrentTabScaffoldingStructure->end()))
			{
				cout << "Error in SubscribeThisAgent function: cannot find tmpOldScaffoldElementIterToDelete in tmpCurrentTabScaffoldingStructure" << endl;
				cout << "VectOldScaffoldElements.size(): " << VectOldScaffoldElements.size() << endl;
				cout << "tmpOldScaffoldSelected: " << tmpOldScaffoldSelected << endl;
				exit(EXIT_FAILURE);
			}
			tmpCurrentTabScaffoldingStructure->erase(tmpOldScaffoldElementIterToDelete);
		}
		tmpCurrentTabScaffoldingStructure->insert(make_pair(tmpCurrentIDAgentToAnalize, Scaffolding(tmpCurrentIDAgentToAnalize, 0)));
	}

	if(tmpCurrentDebugLevel >= 2)
		cout << "SubscribeThisAgent [end]" << endl;
}

void InitScaffoldingStructure(Agents *tmp_Current_TabAgents, ScaffoldingStructure *tmpCurrentTabScaffoldingStructure, 
										SystemParams &tmpCurrentMilovoParam, int tmp_Current_DebugLevel)
{
	vector<Mil_Int> VectIDAgentsLife;
	GetAgentsAlive(VectIDAgentsLife, tmp_Current_TabAgents, tmp_Current_DebugLevel);
	random_shuffle(VectIDAgentsLife.begin(), VectIDAgentsLife.end());
	
	vector<Mil_Int>::iterator VectIDAgentsLifeIter = VectIDAgentsLife.begin();
	for(Mil_Int ScaffoldingMaxLevelIndex = 1; ScaffoldingMaxLevelIndex <= tmpCurrentMilovoParam.GetScaffoldingMaxLevel(); ScaffoldingMaxLevelIndex++)
	{
		Mil_Int tmpCurrentIDAgentToAnalize = *VectIDAgentsLifeIter;
		tmpCurrentTabScaffoldingStructure->insert(make_pair(tmpCurrentIDAgentToAnalize, Scaffolding(tmpCurrentIDAgentToAnalize, 0)));
		VectIDAgentsLifeIter++;
	}
}

void ExtractIDArtifactsBornThisStep(vector<Mil_Int> &tmpVectArtifactsBornThisStep, Artifacts *tmp_TabArtifacts, Mil_Int tmp_IDAgentToAnalize, 
												Agents *tmp_TabAgents, int tmpCurrentStep, int tmpDebugLevel)
{
	Agents::iterator tmp_TabAgentsIter = tmp_TabAgents->find(tmp_IDAgentToAnalize);
	if((tmpDebugLevel >= 0) && (tmp_TabAgentsIter == tmp_TabAgents->end()))
	{
		cout << "Error in ExtractIDArtifactsBornThisStep function: cannot find tmp_TabAgentsIter in tmp_TabAgents: " << tmp_IDAgentToAnalize << endl;
		exit(EXIT_FAILURE);
	}
	for(Artifacts::iterator tmp_TabArtifactsIter = tmp_TabArtifacts->begin(); tmp_TabArtifactsIter != tmp_TabArtifacts->end(); tmp_TabArtifactsIter++)
	{
		Mil_Int FirstStepToView = 1;
		if((tmpCurrentStep > FirstStepToView) &&
			((tmp_TabArtifactsIter->second.GetBornStep() >= (tmpCurrentStep - FirstStepToView) && 
			  (tmp_TabArtifactsIter->second.GetBornStep() <= tmpCurrentStep))) && 
			(tmp_TabArtifactsIter->second.GetIDAgentOwner() != tmp_TabAgentsIter->second.GetID()))
			tmpVectArtifactsBornThisStep.push_back(tmp_TabArtifactsIter->second.GetID());
	}
}

void ExtractIDAgentOwnerArtifactsBornThisStep(vector<Mil_Int> &tmpVectIDAgentOwnerArtifactsBornThisStep, vector<Mil_Int> &tmpVectArtifactsBornThisStep, 
															 Artifacts *tmp_TabArtifacts, int tmpGetDebugLevel)
{
	for(vector<Mil_Int>::iterator tmpVectArtifactsBornThisStepIter = tmpVectArtifactsBornThisStep.begin(); tmpVectArtifactsBornThisStepIter != tmpVectArtifactsBornThisStep.end(); tmpVectArtifactsBornThisStepIter++)
	{
		bool FlagFound = false;
		vector<Mil_Int>::iterator tmpVectIDAgentOwnerArtifactsBornThisStepIter = tmpVectIDAgentOwnerArtifactsBornThisStep.begin();
		while((FlagFound == false) && (tmpVectIDAgentOwnerArtifactsBornThisStepIter != tmpVectIDAgentOwnerArtifactsBornThisStep.end()))
		{
			if(*tmpVectArtifactsBornThisStepIter == *tmpVectIDAgentOwnerArtifactsBornThisStepIter)
				FlagFound = true;
			else tmpVectIDAgentOwnerArtifactsBornThisStepIter++;
		}
		if(FlagFound == false)
		{
			Artifacts::iterator tmp_TabArtifactsIter = tmp_TabArtifacts->find(*tmpVectArtifactsBornThisStepIter);
			if((tmpGetDebugLevel >= 0) && (tmp_TabArtifactsIter == tmp_TabArtifacts->end()))
			{
				cout << "Error in ExtractIDAgentOwnerArtifactsBornThisStep function: cannot find tmp_TabArtifactsIter in tmp_TabArtifacts" << endl;
				exit(EXIT_FAILURE);
			}
			tmpVectIDAgentOwnerArtifactsBornThisStep.push_back(tmp_TabArtifactsIter->second.GetID());
		}
	}
}

Mil_Int GetHowManyCopyThisArtifactInRecipe(Mil_Int tmpIDArtifactToAnalize, Artifacts *tmp_CurrentTabArtifacts, Mil_Int tmpIDRecipeToAnalize, 
														 Recipes *tmp_CurrentTabRecipes, int tmp_CurrentDebugLevel)
{
	Mil_Int HowManyCopyThisArtifact = 0;
	Recipes::iterator tmp_CurrentTabRecipesIter = tmp_CurrentTabRecipes->find(tmpIDRecipeToAnalize);
	if((tmp_CurrentDebugLevel >= 0) && (tmp_CurrentTabRecipesIter == tmp_CurrentTabRecipes->end()))
	{
		cout << "Error in GetHowManyCopyThisArtifactInRecipe function: cannot find tmp_CurrentTabRecipesIter in tmp_CurrentTabRecipes: "<< tmpIDRecipeToAnalize << endl;
		exit(EXIT_FAILURE);
	}
	
	for(list<Mil_Int>::iterator LinksIDArtifactsIter = tmp_CurrentTabRecipesIter->second.LinksIDArtifacts.begin(); LinksIDArtifactsIter != tmp_CurrentTabRecipesIter->second.LinksIDArtifacts.end(); LinksIDArtifactsIter++)
	{
		Mil_Int tmpIDInputToAnalize = *LinksIDArtifactsIter;
		if(tmpIDInputToAnalize == tmpIDArtifactToAnalize)
			HowManyCopyThisArtifact++;
	}
	
	return(HowManyCopyThisArtifact);
}

Mil_Int AdjustOutputOnBoundary(Mil_Int tmpRecipeOutputName, Mil_Int tmpLowBoundary, Mil_Int tmpHighBoundary)
{
	if(tmpRecipeOutputName <= tmpLowBoundary)
		tmpRecipeOutputName = tmpLowBoundary;
	
	if(tmpRecipeOutputName >= tmpHighBoundary)
		tmpRecipeOutputName = tmpHighBoundary;
	
	return(tmpRecipeOutputName); 
}

Mil_Int CheckOutputCopiesThisAgent(Mil_Int tmpRecipeOutputName, vector<Mil_Int> &tmpValueToCompare)
{
	if(tmpRecipeOutputName != 0)
	{
		bool FlagFound = false;
		vector<Mil_Int>::iterator tmpValueToCompareIter = tmpValueToCompare.begin();
		while((FlagFound == false) && (tmpValueToCompareIter != tmpValueToCompare.end()))
		{
			if(tmpRecipeOutputName == *tmpValueToCompareIter)
			{
				tmpRecipeOutputName = 0;
				FlagFound = true;
			}
			  else tmpValueToCompareIter++;
		}
	}

	return(tmpRecipeOutputName);
}

Mil_Int CheckOutputEqualRawMaterials(Mil_Int tmpRecipeOutputName, MilinitParams &tmp_Current_Init_Param)
{
	if(tmpRecipeOutputName != 0)
	{
		bool FlagFound = false;
		vector<Mil_Int>::iterator VectRawMaterialsIter = tmp_Current_Init_Param.VectRawMaterials.begin();
		while(VectRawMaterialsIter != tmp_Current_Init_Param.VectRawMaterials.end())
		{
			if(tmpRecipeOutputName == *VectRawMaterialsIter)
			{
				FlagFound = true;
				tmpRecipeOutputName = 0;
			}
			else VectRawMaterialsIter++;
		}
	}
	
	return(tmpRecipeOutputName);
}

Mil_Int CheckOutputIntoGoalRange(Mil_Int tmpRecipeOutputName, Mil_Int tmp_GoalToCompare)
{
	if(tmpRecipeOutputName != 0)
	{
		Mil_Double Double_tmpRecipeOutputName = (Mil_Double) tmpRecipeOutputName;
		Mil_Double Double_tmp_GoalToCompare = (Mil_Double) tmp_GoalToCompare;
		if((Double_tmpRecipeOutputName < (Double_tmp_GoalToCompare - (Double_tmp_GoalToCompare * 0.1))) ||
			(Double_tmpRecipeOutputName > (Double_tmp_GoalToCompare + (Double_tmp_GoalToCompare * 0.1))))
			tmpRecipeOutputName = 0;
	}
	
	return(tmpRecipeOutputName);
}

Mil_Int InvalidateOutputOnBoundary(Mil_Int tmpRecipeOutputName, Mil_Int tmpLowBoundary, Mil_Int tmpHighBoundary)
{
	if((tmpRecipeOutputName != 0) && ((tmpRecipeOutputName < tmpLowBoundary) || (tmpRecipeOutputName > tmpHighBoundary)))
		tmpRecipeOutputName = 0;
	
	return(tmpRecipeOutputName);
}

Mil_Int AdjustOutputOnTorus(Mil_Int tmpRecipeOutputName, Mil_Int tmpHighBoundary, Mil_Int tmpLowBoundary)
{
	if(tmpRecipeOutputName != 0)
		tmpRecipeOutputName = (tmpRecipeOutputName + tmpHighBoundary) % (tmpHighBoundary - tmpLowBoundary);
	
	return(tmpRecipeOutputName);
}

